/*
 * LineNumber.java
 *
 * Created on July 2, 2007
 *
 */

package ca.compsci.opent.ide;

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;

public class LineNumber extends JComponent
{
	private final static Color DEFAULT_BACKGROUND = new Color(234, 234, 234);
	private final static Color DEFAULT_FOREGROUND = Color.BLACK;
	private final static Font  DEFAULT_FONT = new Font("monospaced", Font.PLAIN, 12);

	//  LineNumber height (abends when I use MAX_VALUE)
	private final static int HEIGHT = Integer.MAX_VALUE - 1000000;

	//  Set right/left margin
	private final static int MARGIN = 5;

	//  Variables for this LineNumber component
	private Font font;
	private FontMetrics fontMetrics;
	private int lineHeight;
	private int currentDigits;

	//  Metrics of the component used in the constructor
	private JComponent component;
	private int componentFontHeight;
	private int componentFontAscent;

	public LineNumber(JComponent component)
	{
		if (component == null)
		{
			setFont( DEFAULT_FONT );
			this.component = this;
		}
		else
		{
			setFont( component.getFont() );
			this.component = component;
		}

		setBackground( DEFAULT_BACKGROUND );
		setForeground( DEFAULT_FOREGROUND );
		setPreferredWidth( 99 );
	}

	public void setPreferredWidth(int lines)
	{
		int digits = String.valueOf(lines).length();

		//Update sizes when number of digits in the line number changes or when the font changes
		if ((digits != currentDigits && digits > 1) ||
		(this.font != super.getFont()))
		{
			currentDigits = digits;
			int width = fontMetrics.charWidth('0') * digits;
			Dimension d = getPreferredSize();
			d.setSize(2 * MARGIN + width, HEIGHT);
			setPreferredSize(d);
			setSize(d);
		}
	}

	public void setFont(Font font)
	{
		super.setFont(font);
		fontMetrics = getFontMetrics(getFont());
		componentFontHeight = fontMetrics.getHeight();
		componentFontAscent = fontMetrics.getAscent();
	}

	public int getLineHeight()
	{
		if (lineHeight == 0)
			return componentFontHeight;
		else
			return lineHeight;
	}

	public void setLineHeight(int lineHeight)
	{
		if (lineHeight > 0)
			this.lineHeight = lineHeight;
	}

	public int getStartOffset()
	{
		return component.getInsets().top + componentFontAscent;
	}

	public void paintComponent(Graphics g)
	{
		int lineHeight = getLineHeight();
		int startOffset = getStartOffset();
		Rectangle drawHere = g.getClipBounds();

		// Paint the background
		g.setColor(getBackground());
		g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);

		//  Determine the number of lines to draw in the foreground.
		g.setColor(getForeground());
		int startLineNumber = (drawHere.y / lineHeight) + 1;
		int endLineNumber = startLineNumber + (drawHere.height / lineHeight);

		int start = (drawHere.y / lineHeight) * lineHeight + startOffset;

		for (int i = startLineNumber; i <= endLineNumber; i++)
		{
			String lineNumber = String.valueOf(i);
			int stringWidth = fontMetrics.stringWidth( lineNumber );
			int rowWidth = getSize().width;
			g.drawString(lineNumber, rowWidth - stringWidth - MARGIN, start);
			start += lineHeight;
		}

		int rows = component.getSize().height / componentFontHeight;
		setPreferredWidth( rows );
	}
}